#pragma once
#ifndef STUDIO_MACROS_H
#define STUDIO_MACROS_H

// 标准c++头文件
// 输入输出库
#include <iostream>
#include <sstream>
// 字符串库
#include <string>
// 容器
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <list>
#include <queue>
#include <stack>
// 算法库
#include <algorithm>
// 数值库
#include <cmath>
#include <numeric>
#include <random>
// 时间库
#include <chrono>
// 文件和流库
#include <fstream>
#include <filesystem>
//#include <dirent.h>
// 异常处理库
#include <stdexcept>
// 内存管理库
#include <memory>
// 多线程库
#include <thread>
#include <mutex>
#include <future>
#include <atomic>
#include <functional>
// c++ 17 新的头文件
#include <any>          // 提供了一个类型安全的工具，可以存储单个值的任意类型。
#include <optional>     // 提供了一个模板类，用于表示可选的（有或没有值的）对象。
#include <string_view>  // 提供了对字符序列的非拥有、不可修改的引用。
#include <variant>      // 类似于联合（union），但是更安全和更易用，可以保存其中列出的任何数据类型。

// 标准c头文件
#include <stdio.h>   // 标准输入输出库
#include <stdlib.h>  // 标准库头文件，包括内存分配、程序控制、数学运算等
#include <string.h>  // 字符串处理库
#include <math.h>    // 数学函数库
#include <ctype.h>   // 字符类型库
#include <limits.h>  // 定义各种变量类型的属性
#include <assert.h>  // 提供断言测试支持
#include <errno.h>   // 错误号定义库
#include <time.h>    // 时间日期库
#include <locale.h>  // 本地化支持库
#include <stddef.h>  // 定义许多常用的类型和宏
#include <signal.h>  // 信号处理库
#include <regex>
//

#include <clocale>

#include <codecvt>
#include <cstring>
#include <locale>

#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <float.h>

//// 数据库
//// #include <sql.h>
//// #include <sqlext.h>
#if WIN32
// 注意这个顺序,一定是先Windows.h, 后winsock2.h
#include <Windows.h>
#include <winsock2.h>
#pragma comment(lib, "WSOCK32")
#pragma comment(lib, "ws2_32")

#include <psapi.h>
#include <io.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/mman.h>
#include <unistd.h>
#ifndef O_BINARY
#define O_BINARY 0
#endif
#endif

#if WIN32
using silly_handle = HANDLE;
#else
using silly_handle = int;
#ifndef INVALID_HANDLE_VALUE
#define INVALID_HANDLE_VALUE -1
#endif
#endif

// π
#ifndef AO_PI
#define AO_PI (3.1415926535897932384626433832795028841971693993751f)
#endif

// π
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

// π/2
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif

// 自然指数e
#ifndef BASE_E
#define BASE_E 2.71828182845904523536
#endif

// 最小浮点数
#ifndef TINY
#define TINY (1e-18)
#endif

// 一个极小的浮点数, 用于浮点数比较		EPS 与opencv的冲突
#ifndef AO_EPSILON
#define AO_EPSILON (.1e-18)
#endif

#ifndef AO_MAX
#define AO_MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif

#ifndef AO_MIN
#define AO_MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif

// 转化小端序的int值
#define AO_CONVERT_LITTLE_ENDIAN_LONG(src_ptr) (src_ptr[3] << 24 | (src_ptr[2] << 16) | src_ptr[1] << 8 | src_ptr[0])
// 转化小端序的int值
#define AO_CONVERT_LITTLE_ENDIAN_INT(src_ptr) (src_ptr[3] << 24 | (src_ptr[2] << 16) | src_ptr[1] << 8 | src_ptr[0])
// 转化小端序的short值
#define AO_CONVERT_LITTLE_ENDIAN_SHORT(src_ptr) (src_ptr[1] << 8) + src_ptr[0]

#ifndef AO_FILE_NAME
// 获取当前文件名称
#if IS_WIN32
#define AO_FILE_NAME (strrchr(__FILE__, '\\') ? (strrchr(__FILE__, '\\') + 1) : __FILE__)
#else
#define AO_FILE_NAME (strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/') + 1) : __FILE__)
#endif
#endif

#define AO_PRINTF_COLOR_NONE "\033[m"
#define AO_PRINTF_COLOR_RED "\033[0;32;31m"
#define AO_PRINTF_COLOR_LIGHT_RED "\033[1;31m"
#define AO_PRINTF_COLOR_GREEN "\033[0;32;32m"
#define AO_PRINTF_COLOR_LIGHT_GREEN "\033[1;32m"
#define AO_PRINTF_COLOR_BLUE "\033[0;32;34m"
#define AO_PRINTF_COLOR_LIGHT_BLUE "\033[1;34m"
#define AO_PRINTF_COLOR_DARK_GRAY "\033[1;30m"
#define AO_PRINTF_COLOR_CYAN "\033[0;36m"
#define AO_PRINTF_COLOR_LIGHT_CYAN "\033[1;36m"
#define AO_PRINTF_COLOR_PURPLE "\033[0;35m"
#define AO_PRINTF_COLOR_LIGHT_PURPLE "\033[1;35m"
#define AO_PRINTF_COLOR_BROWN "\033[0;33m"
#define AO_PRINTF_COLOR_YELLOW "\033[1;33m"
#define AO_PRINTF_COLOR_LIGHT_GRAY "\033[0;37m"
#define AO_PRINTF_COLOR_WHITE "\033[1;37m"

#ifndef AO_PRINTF
// 打印信息 未封装
#define AO_PRINTF(s, ...)
#endif

#ifndef AO_INFO_PRINT
// 打印提示信息
#define AO_INFO_PRINT(s, ...) printf(AO_PRINTF_COLOR_CYAN "\n[INFO] %s:%I32d \n " s AO_PRINTF_COLOR_NONE " \n", AO_FILE_NAME, __LINE__, ##__VA_ARGS__);
#endif

#ifndef AO_ERROR_PRINT
// 打印错误信息
#define AO_ERROR_PRINT(s, ...) printf(AO_PRINTF_COLOR_RED "\n[ERROR] %s:%I32d \n ... " s AO_PRINTF_COLOR_NONE, AO_FILE_NAME, __LINE__, ##__VA_ARGS__);
#endif


#ifndef AO_DEBUG_PRINT
// 打印调试信息
#ifndef NDEBUG
#define AO_DEBUG_PRINT(s, ...) printf(AO_CONSOLE_BROWN "\n[DEBUG] %s:%I32d \n ... " s AO_CONSOLE_NONE " \n", AO_FILE_NAME, __LINE__, ##__VA_ARGS__);

#else
#define AO_DEBUG_PRINT(s, ...)
#endif
#endif

#define DEG2RAD(deg) ((deg) * AO_PI / 180.0)
#define RAD2DEG(rad) ((rad) * 180.0 / AO_PI)

#ifndef TINY
#define TINY (1e-18)
#endif
#define AO_TINY TINY


/// 控制台信息print, 如果需要记录日志,使用 log/silly_log.h
#if WIN32
// windows 在控制台,以utf8编码输出
#define WINDOWS_UTF8_PAGE                                                      \
    {                                                                          \
        SetConsoleOutputCP(65001);                                             \
        CONSOLE_FONT_INFOEX info = {0};                                        \
        info.cbSize = sizeof(info);                                            \
        info.dwFontSize.Y = 16;                                                \
        info.FontWeight = FW_NORMAL;                                           \
        wcscpy_s(info.FaceName, L"Consolas");                                  \
        SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), NULL, &info); \
    }
#else
#define WINDOWS_UTF8_PAGE
#endif



#ifndef SUM_MEM_DEL_ARR
// 内存释放 delete []
#define SUM_MEM_DEL_ARR(p) \
    if ((p))               \
    {                      \
        delete[] (p);      \
        (p) = nullptr;     \
    }
#endif

#endif  // STUDIO_MACROS_H
